import { ReportType } from './constant';
import { ReportParams } from './types';
import Utils from './utils';
/**
 * 爆光上报(是否可见浏览过)
 */

export default class Exposure {
	observer!: IntersectionObserver;
	mutationObserver!: MutationObserver;
	reportedElements: WeakSet<Element> = new WeakSet();
	newElementsFound = false;
	maxRetries = 10; // 最大重试次数
	retryCount = 0; // 当前重试次数
	isInit = false;
	constructor(private callback: (params: ReportParams) => void) {
		Utils.log('曝光监控初始化成功');
		this.setupObservers();
		this.init();
	}

	// 初始化曝光监控
	setupObservers() {
		// 创建 IntersectionObserver 监控元素曝光
		this.observer = new IntersectionObserver(entries => {
			entries.forEach(entry => {
				const element = entry.target;

				// 检查元素是否已经上报过
				if (this.reportedElements.has(element)) {
					// 已上报的元素停止观察
					this.observer.unobserve(element);
					return;
				}

				const exposureData = element.getAttribute('data-exposure');

				// 当元素进入视口且达到可见比例阈值
				if (entry.intersectionRatio > 0 && exposureData) {
					// 标记元素已上报
					this.reportedElements.add(element);

					// 上报曝光数据
					this.callback({
						type: ReportType.EXPOSURE,
						message: '曝光埋点',
						data: exposureData,
					});

					// 停止观察该元素
					this.observer.unobserve(element);
				}
			});
		});

		// 创建 MutationObserver 监控动态元素
		this.mutationObserver = new MutationObserver(mutations => {
			mutations.forEach(mutation => {
				// 处理新增节点
				mutation.addedNodes.forEach(node => {
					if (node instanceof HTMLElement) {
						this.processNewElement(node);
					}
				});
			});
		});
	}

	// 处理新元素及其子元素
	processNewElement(element: HTMLElement) {
		// 检查元素本身是否有曝光属性
		if (
			element.hasAttribute('data-exposure') &&
			!this.reportedElements.has(element)
		) {
			this.observer.observe(element);
		}

		// 检查子元素是否有曝光属性
		const exposureElements = element.querySelectorAll('[data-exposure]');
		exposureElements.forEach(el => {
			if (!this.reportedElements.has(el)) {
				this.observer.observe(el);
			}
		});
	}

	// 扫描并观察页面元素
	private observePageElements() {
		const exposures = document.querySelectorAll('[data-exposure]');
		exposures.forEach(element => {
			if (!this.reportedElements.has(element)) {
				this.observer.observe(element);
			}
			this.newElementsFound = true;
		});
		return this.newElementsFound;
	}

	// 安全重试机制
	safeRetry() {
		if (this.retryCount >= this.maxRetries) {
			Utils.log('warn', '达到最大重试次数(10次)，停止尝试');
			return;
		}

		this.retryCount++;
		setTimeout(() => {
			if (!this.observePageElements()) {
				this.safeRetry();
			}
		}, 100);
	}

	// 初始化和扫描页面元素
	scanAndObserve() {
		if (!this.observePageElements()) {
			this.safeRetry();
		}
	}

	// 强制重新扫描和观察页面元素
	forceObservers() {
		this.resetExposureState();
		this.scanAndObserve();
	}

	// 重置曝光状态
	resetExposureState() {
		// this.observer.disconnect();
		this.reportedElements = new WeakSet();
		this.retryCount = 0;
	}

	// 初始化监控
	init() {
		// 监听页面加载
		window.addEventListener('load', () => {
			if (this.isInit) return;
			this.isInit = true;
			this.resetExposureState();
			this.scanAndObserve();
		});

		// 监听路由变化
		Utils.routerChangeListener(() => {
			if (this.isInit) return;
			this.isInit = true;
			this.resetExposureState();
			this.scanAndObserve();
		});

		// 开始监控DOM变化
		this.mutationObserver.observe(document.body, {
			childList: true,
			subtree: true,
		});
	}
}
